package com.sz.biz.logistics.ord.service.impl;

import com.google.common.collect.Lists;
import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.logistics.ord.service.BizOperationLogService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.biz.logistics.constants.ErrorCodes;
import com.sz.biz.logistics.ord.entity.OrdOrder;
import com.sz.biz.logistics.ord.entity.OrdOrderFile;
import com.sz.biz.logistics.ord.entity.OrdOrderFileTypeEnum;
import com.sz.biz.logistics.ord.entity.OrderStatus;
import com.sz.biz.logistics.ord.service.OrdOrderFileService;
import com.sz.biz.logistics.ord.service.OrdOrderService;
import com.sz.biz.logistics.ord.dto.OrdOderFileTypeDto;
import com.sz.biz.logistics.ord.dto.OrdOrderFileDto;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.entity.SysDict;
import com.sz.common.core.system.entity.SysFile;
import com.sz.common.core.system.service.SysDictService;
import com.sz.common.core.system.service.SysFileService;
import com.sz.common.core.system.dto.UserDto;
import com.sz.common.core.system.entity.User;
import com.sz.common.core.system.service.UserService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Package: com.sz.biz.logistics.ord.service.impl<br>
 * Function: 订单-附件serviceimpl <br>
 * Author: yanhong.xiao.<br>
 * Date: 2017-08-07 11:27:00.
 */
@Service("ordOrderFileService")
public class OrdOrderFileServiceImpl extends AbstractService implements OrdOrderFileService {


    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.ord.entity.mapper.OrdOrderFileMapper";
    }

    @Autowired
    private SysDictService dictService;
    @Autowired
    private OrdOrderService orderService;
    @Autowired
    private SysFileService sysFileService;
    @Autowired
    private UserService userService;
    @Autowired
    private CustomerUserService customerUserService;
    @Autowired
    private BizOperationLogService bizOperationLogService;


    @Override
    public List<OrdOderFileTypeDto> queryOrderFileTypes(OrdOrderFileTypeEnum fileType) {
        List<OrdOderFileTypeDto> resultList = Lists.newArrayList();
        List<SysDict> dictList = dictService.queryOrderFileTypes(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG, fileType.getName());
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(dictList)) {
            dictList.forEach(dict -> {
                OrdOderFileTypeDto typeDto = new OrdOderFileTypeDto();
                EntityUtils.copyPropertiesIgnoreNull(dict, typeDto);
                resultList.add(typeDto);
            });
        }
        return resultList;
    }


    @Override
    public void saveOrdFiles(Integer createUserType, String orderNo, OrderStatus orderStatus, List<OrdOrderFileDto> fileDtoList) {
        if (CollectionUtils.isNotEmpty(fileDtoList)) {
            List<OrdOrderFile> fileList = Lists.newArrayList();
            fileDtoList.forEach(fileDto -> {
                OrdOrderFile file = new OrdOrderFile();
                EntityUtils.copyPropertiesIgnoreNull(fileDto, file);
                file.setCreateUserType(createUserType);
                file.setOrderNo(orderNo);
                file.setCreateUserId(PrincipalUtils.getAccountId());
                file.setLastUpdateUserId(PrincipalUtils.getAccountId());
                file.setOrderStatus(orderStatus);
                fileList.add(file);
            });
            //保存到数据库
            dao.batchInsert(getSqlName("insertSelective"), fileList);
            //保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("ADD_ORDER_FILE", fileList);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_FILE, UserActions.ADD, "添加订单附件", dataBackup);
        }

    }

    @Override
    public Boolean checkFile(OrderStatus orderStatus, List<OrdOrderFileDto> fileDtoList) {
        //校验附件的名称
        checkUniqueName(fileDtoList);
        //校验附件的状态是否和订单的状态匹配
        checkFileStatus(orderStatus, fileDtoList);
        return true;
    }


    /**
     * return false ; 表示，有重复名字.
     * return true ; 表示无重复名字
     *
     * @param fileDtoList
     * @return
     */
    @Override
    public Boolean checkUniqueName(List<OrdOrderFileDto> fileDtoList) {
        if (CollectionUtils.isNotEmpty(fileDtoList)) {
            Map<String, Object> map = new HashedMap();
            for (OrdOrderFileDto fileDto :
                    fileDtoList) {
                if (map.containsKey(fileDto.getFileName())) {
                    //map中已经有这个filename了，表示名字重复了
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NAME_EXIST);
                }
                map.put(fileDto.getFileName(), fileDto);
            }
        }
        return true;
    }

    /**
     * 校验订单附件 是否和订单的状态匹配
     *
     * @param orderStatus：订单的状态
     * @param fileDtoList:附件
     * @return
     */
    @Override
    public Boolean checkFileStatus(OrderStatus orderStatus, List<OrdOrderFileDto> fileDtoList) {
        if (CollectionUtils.isNotEmpty(fileDtoList)) {
            OrdOrderFileTypeEnum typeEnum = OrdOrderFileTypeEnum.valueOfEnum(orderStatus.getCode());
            if (null != typeEnum) {
                String prefix = typeEnum.getName();
                for (OrdOrderFileDto file :
                        fileDtoList) {
                    String code = file.getCode();
                    if (!code.startsWith(prefix) && !code.startsWith(CommCodes.ORDER_FILE_COMMON_PREFIX)) {
                        throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_STATUS_NOT_MATCH);
                    }

                }
            } else {
                throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_STATUS_NOT_MATCH);
            }
        }

        return true;
    }


    /**
     * return false ; 表示，有重复名字.
     * return true ; 表示无重复名字
     *
     * @param orderNo
     * @param fileName
     * @return
     */
    @Override
    public Boolean checkUniqueName(String orderNo, String fileName) {
        ParamData pd = new ParamData();
        pd.put("orderNo", orderNo);
        pd.put("fileName", fileName);
        OrdOrderFile file = (OrdOrderFile) dao.findForObject(getSqlName("getByOrderAndFileName"), pd);
        if (null != file) {
            return false;
        }
        return true;
    }

    /**
     * 检查新提交的文件有没有文件名称重复
     * 检查有没有文件名称在数据库中重复
     * 保存
     *
     * @param orderNo
     * @param fileDtoList
     * @return
     */
    @Override
    public Boolean batchAddOrderFiles(String orderNo, List<OrdOrderFileDto> fileDtoList) {
        checkUniqueName(fileDtoList);
        //去数据库检查，有没有文件名称在数据库中存在了
        List<OrdOrderFile> oldFileList = queryByOrderNo(orderNo);
        if (CollectionUtils.isNotEmpty(oldFileList)) {
            //原来有文件了，需要检查当前的文件在原来文件名称中是否存
            Map<String, Object> map = new HashedMap();
            oldFileList.forEach(oldFile -> {
                map.put(oldFile.getFileName(), oldFile);
            });
            fileDtoList.forEach(fileDto -> {
                if (map.containsKey(fileDto.getFileName())) {
                    //存在
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NAME_EXIST);
                }
            });

        }
        //保存
        // saveOrdFiles(orderNo, fileDtoList);
        return true;
    }

    @Override
    public List<OrdOrderFile> queryByOrderNo(String orderNo) {

        return dao.findForList(getSqlName("queryByOrderNo"), orderNo, OrdOrderFile.class);

    }

    /**
     * 增加附件
     * 订单是否存在
     * 文件的名称唯一性校验
     * 文件的状态需要和订单的状态一致
     *
     * @param fileDto
     */
    @Override
    public Integer addOrderFileDto(OrdOrderFileDto fileDto) {
        OrdOrder ordOrder = orderService.findByOrderNo(fileDto.getOrderNo());
        if (null == ordOrder) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_NOT_EXIST);
        }
        OrdOrderFile file = new OrdOrderFile();
        //检查文件名是否唯一
        if (checkUniqueName(fileDto.getOrderNo(), fileDto.getFileName())) {
            //检测状态
            List<OrdOrderFileDto> fileDtoLIst = Lists.newArrayList();
            fileDtoLIst.add(fileDto);
            checkFileStatus(ordOrder.getOrderStatus(), fileDtoLIst);
            EntityUtils.copyPropertiesIgnoreNull(fileDto, file);
            file.setCreateUserId(PrincipalUtils.getAccountId());
            file.setLastUpdateUserId(PrincipalUtils.getAccountId());
            file.setOrderStatus(ordOrder.getOrderStatus());
            //客户系统，自己只能给自己添加附件。
            //2017-11 需求更改,客户系统，改为主账号可以对下面的子账号的附件进行处理。 子账号只能对自己的账号进行处理
            if (fileDto.getCreateUserType().intValue() == CommCodes.CUSTOMER_USER_TYPE) {
                //获取当前用户，判断是子账号还是主账号
                checkUserAuth(ordOrder);
            }
            dao.save(getSqlName("insertSelective"), file);
        } else {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NAME_EXIST);
        }
        // 日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_ORD_ORDER_FILE", fileDto);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_FILE, UserActions.ADD, "新增订单附件", dataBackup);
        //订单附件的操作日志增加  add  2017-10
        String fileTypeName = dictService.getNameByCode(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG, fileDto.getCode());
        fileDto.setFileTypeName(fileTypeName);

        Integer accountId = PrincipalUtils.getAccountId();
        Integer domainId = PrincipalUtils.getDomainId();
        bizOperationLogService.saveOrderFileUpdateLog(ordOrder.getId(), ordOrder.getOrderStatus(), UserActions.ADD, fileDto,accountId,domainId);
        return file.getId();
    }

    /**
     * 删除附件
     * <p>
     * 附加是否存在
     * 订单是否存在，
     * 附件和订单是否匹配
     * 该状态是否可以删掉（运营系统的人可以删除任何状态的附件，客户系统的人只可以删除当前状态的文件）
     * <p>
     * 客户系统的操作，在已经提交状态下可以删除草稿状态的附件
     *
     * @param orderNo
     * @param orderFileId
     * @param userType    来自CommCodes
     */
    @Override
    public void deleteOrderFile(String orderNo, Integer orderFileId, String userType) {
        OrdOrderFile ordOrderFile = findById(orderFileId);
        if (null == ordOrderFile) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NOT_EXIST);
        }
        OrdOrder ordOrder = orderService.findByOrderNo(orderNo);
        if (null == ordOrder) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_NOT_EXIST);
        }
        if (!ordOrderFile.getOrderNo().equals(ordOrder.getOrderNo())) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NOT_EXIST);
        }
        if (userType.equals(CommCodes.CUSTOMER)) {
            //客户系统的操作
            //如果当前是已提交状态
            if (ordOrder.getOrderStatus().compareTo(OrderStatus.COMMITED) > 0) {
                if (ordOrderFile.getOrderStatus() != ordOrder.getOrderStatus()) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_CAN_NOT_DELETE);
                }
            }
            //add 2017-11  需求变更， 主账号可以删除子账号上传的附件，子账号只能删除自己创建的附件
            //获取当前用户，判断是子账号还是主账号
            checkUserAuth(ordOrder);
        }
        //附件的删除
        dao.delete(getSqlName("deleteByPrimaryKey"), orderFileId);
        // 日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_ORD_ORDER_FILE", orderFileId);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_FILE, UserActions.DELETE, "删除订单附件", dataBackup);
        //订单附件的操作日志增加  add  2017-10
        OrdOrderFileDto fileDto = new OrdOrderFileDto();
        EntityUtils.copyPropertiesIgnoreNull(ordOrderFile, fileDto);
        String fileTypeName = dictService.getNameByCode(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG, fileDto.getCode());
        fileDto.setFileTypeName(fileTypeName);
        Integer accountId = PrincipalUtils.getAccountId();
        Integer domainId = PrincipalUtils.getDomainId();
        bizOperationLogService.saveOrderFileUpdateLog(ordOrder.getId(), ordOrder.getOrderStatus(), UserActions.DELETE, fileDto,accountId,domainId);
    }

    @Override
    public OrdOrderFile findById(Integer orderFileId) {
        return (OrdOrderFile) dao.findForObject(getSqlName("selectByPrimaryKey"), orderFileId);
    }

    /**
     * 分页获取某个订单下的附件列表
     *
     * @param params
     * @return
     */
    @Override
    public ResultDto findFileDtoPages(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        List<OrdOrderFileDto> dtoList = Lists.newArrayList();
        List<OrdOrderFile> fileList = dao.findForList(getSqlName("findListPage"), pd, OrdOrderFile.class);
        if (CollectionUtils.isNotEmpty(fileList)&& !StringUtils.isEmpty(pd.get("orderNo"))) {
            List<String> fileIds = Lists.newArrayList();
            //运营系统创建者id
            List<Integer> operCreateUserIds = Lists.newArrayList();
            //客户系统创建者id
            List<Integer> cusCreateUserIds = Lists.newArrayList();
            fileList.forEach(ordOrderFile -> {
                fileIds.add(ordOrderFile.getFileId());
                if (ordOrderFile.getCreateUserType().intValue() == CommCodes.OPERATOR_USER_TYPE.intValue()) {
                    operCreateUserIds.add(ordOrderFile.getCreateUserId());
                } else if (ordOrderFile.getCreateUserType().intValue() == CommCodes.CUSTOMER_USER_TYPE.intValue()) {
                    cusCreateUserIds.add(ordOrderFile.getCreateUserId());
                }
            });

            Map<String, SysFile> fileMap = new HashedMap();
            //获取文件信息
            if (CollectionUtils.isNotEmpty(fileIds)) {
                List<SysFile> files = sysFileService.getFileInfos(fileIds);
                if (CollectionUtils.isNotEmpty(files)) {
                    files.forEach(file -> {
                        fileMap.put(file.getFileId(), file);
                    });
                }
            }
            //获取创建人,分客户系统和运营系统
            Map<Integer, Object> sysUserMap = new HashedMap();
            if (CollectionUtils.isNotEmpty(operCreateUserIds)) {
                List<User> sysUserList = userService.findByIds(operCreateUserIds);
                if (CollectionUtils.isNotEmpty(sysUserList)) {
                    sysUserList.forEach(u -> {
                        sysUserMap.put(u.getId(), u);
                    });
                }
            }
            Map<Integer, Object> cusUserMap = new HashedMap();
            if (CollectionUtils.isNotEmpty(cusCreateUserIds)) {
                List<CusUser> cusUserList = customerUserService.findByIds(cusCreateUserIds);
                if (CollectionUtils.isNotEmpty(cusUserList)) {
                    cusUserList.forEach(cu -> {
                        cusUserMap.put(cu.getId(), cu);
                    });
                }
            }

            //获取数据库的所有文件配置
            List<SysDict> dictList = dictService.queryOrderFileTypes(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG, null);
            Map<String, SysDict> dictMap = new HashedMap();
            if (CollectionUtils.isNotEmpty(dictList)) {
                dictList.forEach(sysDict -> {
                    dictMap.put(sysDict.getCode(), sysDict);
                });
            }

            fileList.forEach(ordOrderFile -> {
                OrdOrderFileDto dto = new OrdOrderFileDto();
                EntityUtils.copyPropertiesIgnoreNull(ordOrderFile, dto);
                dto.setFileTypeName(null == dictMap.get(dto.getCode()) ? null : dictMap.get(dto.getCode()).getName());


                SysFile file = fileMap.get(dto.getFileId());
                if (null != file) {
                    dto.setFileUrl(file.getFileLocation());
                    dto.setFileType(file.getContentType());
                    dto.setFileRandomName(file.getFileName());
                }
                if (ordOrderFile.getCreateUserType().intValue() == CommCodes.OPERATOR_USER_TYPE.intValue()) {
                    //运营系统
                    User u = (User) sysUserMap.get(ordOrderFile.getCreateUserId());
                    if (null != u) {
                        dto.setCreateUserName(u.getUserName());
                    }
                } else if (ordOrderFile.getCreateUserType().intValue() == CommCodes.CUSTOMER_USER_TYPE.intValue()) {
                    CusUser cu = (CusUser) cusUserMap.get(ordOrderFile.getCreateUserId());
                    if (null != cu) {
                        dto.setCreateUserName(cu.getUserName());
                    }
                }
                dtoList.add(dto);
            });
        }
        return new QResultDto(dtoList, pd.getPagination());
    }

    @Override
    public OrdOrderFileDto getByOrderFileId(Integer orderFileId) {
        OrdOrderFileDto dto = new OrdOrderFileDto();
        OrdOrderFile orderFile = (OrdOrderFile) dao.findForObject(getSqlName("selectByPrimaryKey"), orderFileId);
        if (null != orderFile) {

            //获取数据库的所有文件配置
            List<SysDict> dictList = dictService.queryOrderFileTypes(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG, null);
            Map<String, SysDict> dictMap = new HashedMap();
            if (CollectionUtils.isNotEmpty(dictList)) {
                dictList.forEach(sysDict -> {
                    dictMap.put(sysDict.getCode(), sysDict);
                });
            }

            //处理创建人，创建时间
            EntityUtils.copyPropertiesIgnoreNull(orderFile, dto);
            if (orderFile.getCreateUserType().intValue() == CommCodes.OPERATOR_USER_TYPE.intValue()) {
                UserDto u = userService.getUserById(orderFile.getCreateUserId());
                dto.setCreateUserName(u.getUserName());
            } else if (orderFile.getCreateUserType().intValue() == CommCodes.CUSTOMER_USER_TYPE.intValue()) {
                CusUser cu = customerUserService.findById(orderFile.getCreateUserId());
                dto.setCreateUserName(cu.getUserName());
            }

            dto.setFileTypeName(null == dictMap.get(dto.getCode()) ? null : dictMap.get(dto.getCode()).getName());
        }

        return dto;
    }

    /**
     * 根据订单号，更新订单号
     *
     * @param oldOrderNo
     * @param newOrderNo
     */
    @Override
    public void updateOrderNoByOrderNo(String oldOrderNo, String newOrderNo) {
        if (StringUtils.isEmpty(oldOrderNo) || StringUtils.isEmpty(newOrderNo)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "订单号不能为空！");
        }
        ParamData pd = new ParamData();
        pd.put("newOrderNo", newOrderNo);
        pd.put("oldOrderNo", oldOrderNo);
        dao.update(getSqlName("updateOrderNoByOrderNo"), pd);
    }

    @Override
    public void batchSaveOrderFiles(List<OrdOrderFile> ordOrderFiles) {
        if (CollectionUtils.isNotEmpty(ordOrderFiles)) {
            dao.batchInsert(getSqlName("insert"), ordOrderFiles);
        }
    }


    private void checkUserAuth(OrdOrder ordOrder) {
        Integer cusUserId = PrincipalUtils.getAccountId();
        if (null != cusUserId) {
            //当前用户
            CusUser cusUser = customerUserService.findById(cusUserId);
            if (cusUser.getIsSystem()) {
                //主账号
                if (cusUser.getRefCustomerId().intValue() != ordOrder.getCustomerId().intValue()) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NO_AUTH);
                }
            } else {
                //子账号,非自己的订单，不能删除文件
                if (cusUser.getId().intValue() != ordOrder.getCusUserId().intValue()) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NO_AUTH);
                }
            }
        }

    }



}
